/*
 * Copyright 2010 Original Author(s)
 * 
 * This file is part of Kommando
 * 
 * Kommando is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Kommando is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Kommando.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.kommando.application.win32;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.kommando.application.core.Application;
import org.kommando.application.core.ApplicationProvider;
import org.kommando.core.util.Assert;
import org.kommando.filesystem.core.FileSource;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Variant;

/**
 * win32 {@link ApplicationProvider} implementation.
 * <p>
 * Uses the ActiveX WScript.Shell object to load the installed applications
 * 
 * @author Peter De Bruycker
 */
public class Win32ApplicationProvider implements ApplicationProvider {

    private Win32ApplicationContext context;

    public Win32ApplicationProvider(Win32ApplicationContext context) {
        Assert.argumentNotNull("context", context);

        this.context = context;
    }

    @Override
    public List<Application> getApplications() {
        List<Application> applications = new ArrayList<Application>();

        ComThread.InitSTA();

        ActiveXComponent shell = new ActiveXComponent("WScript.Shell");
        String programs = shell.invoke("SpecialFolders", new Variant("Programs")).getString();
        String allUserPrograms = shell.invoke("SpecialFolders", new Variant("AllUsersPrograms")).getString();

        collectApplications(programs, applications);
        collectApplications(allUserPrograms, applications);

        shell.safeRelease();

        ComThread.Release();

        return applications;
    }

    private void collectApplications(String directory, List<Application> results) {
        FileSource fileSource = new FileSource(directory, false, false, -1, Arrays.asList(".exe", ".lnk"));

        for (File file : fileSource.getFiles()) {
            // TODO if file is .lnk, follow, then check if is .exe
            results.add(new Win32Application(context, file));
        }
    }

}
